package com.huishu.commons.utlis;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.HashSet;
import java.util.Set;

public class GenCodeUtil {

    final static String[] chars = new String[]{"0", "1", "2", "3", "4", "5",

            "6", "7", "8", "9", "A", "C", "D", "E", "F", "G", "H",

            "J", "K", "M", "N", "P", "R", "S", "T",

            "U", "V", "W", "X", "Y", "Z"};

    public static String codeGenUtil(String id, Integer len) {
        int index = 0;
        String code;
        do {
            code = genInviteCode(id, len);
            if (!StringUtils.isNumeric(code)) {
                return code;
            }
            id = code + id + System.nanoTime();
            index++;
        } while (index < 20);
        if (StringUtils.isNumeric(code)) {

            return codeGenUtil(UuidUtils.getUUID(), 6);
        }
        return code;
    }

    //传入的加密密钥id必须唯一的，比如用户id、用户ip，我这是优惠券id
    //参数len 是你要生成该随机码的长度，要生成5位的就传5
    private static String genInviteCode(String id, Integer len) {
        // 对传入id进行 MD5 加密，生成32位字符串，是唯一的
        String sMD5EncryptResult = DigestUtils.md5Hex(id + System.currentTimeMillis());
        StringBuilder stringBuilder = new StringBuilder();
        Integer subLen = sMD5EncryptResult.length() / len;
        for (int i = 0; i < len; i++) {
            // 把加密字符按照 sublen 位一组 16 进制与 0x3FFFFFFF（30位1） 进行位与运算（作用：将生成的long型数据控制在30位）
            String sTempSubString = sMD5EncryptResult.substring(i * subLen, (i + 1) * subLen);
            // 这里需要使用 long 型来转换，因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用
            // long ，则会越界与 0x3FFFFFFF（30位1） 进行位与运算（作用：因为long是64位，将生成的long型数据控制在30位）
            long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);//

            // 把得到的值与 0x0000001f 进行位与运算（作用，0x0000001f是16进制，转化为10进制为31，二进制00001111，这个位运算作用就是为了将index控制在31以内）
            // 取得字符数组 chars 索引//
            Long index = 0x0000001f & lHexLong;
            if (index.compareTo(Long.valueOf(chars.length)) >= 0) {
                index = Long.valueOf(chars.length - 1);
            }
            // 把取得的字符相加
            String outChars = chars[index.intValue()];
            // 把字符串存入对应索引的输出数组
            stringBuilder.append(outChars);
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        for (int i = 1; i <= 100000; i++) {
            String uuid = UuidUtils.getUUID();
            String code = codeGenUtil(uuid, 8);
            set.add(code);
            System.out.println(code);
        }
        System.out.println(set.size());
    }
}
